﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace eyetracker
{    
    public partial class netEyes : Form
    {
        //load graphics, set standard variables
        Graphics g;
        int eyeWidth = 100;
        int eyeHeight = 60;
        
        //for the drawing condition (eye opened or not)
        bool leftEyeOpened = true;
        bool rightEyeOpened = true;

        //left eye + pupil position + eye center
        Point leftEyePos;
        Point leftPupilPos;
        Point leftEyeCenter;

        //right eye + pupil position + eye center
        Point rightEyePos;
        Point rightPupilPos;
        Point rightEyeCenter;

        //
        Point delta;
        int deg;
        Size pupilSize = new Size(15,15);
        Pen EyePen = new Pen(Color.Black,3);

        //brushes
        SolidBrush PupilBrush = new SolidBrush(Color.Black);
        SolidBrush RectangleColor = new SolidBrush(Color.DarkGray);
        SolidBrush eyeColor = new SolidBrush(Color.Azure);
        SolidBrush closedEyeColor = new SolidBrush(Color.Blue);

        //rectangles for both eyes
        Rectangle leftEye;
        Rectangle leftPupil;

        Rectangle rightEye;
        Rectangle rightPupil;

        Rectangle background;
        Point mousePoint;

        //main function
        public netEyes()
        {
            this.SetStyle(
                ControlStyles.AllPaintingInWmPaint |
                ControlStyles.UserPaint |
                ControlStyles.DoubleBuffer, true);

            InitializeComponent();
            this.ResizeRedraw = true;
            
            background = new Rectangle(0, 0, this.Width, this.Height);
            leftEyePos = new Point((this.Width / 2) - (eyeWidth) - 2, (this.Height / 2) - (eyeHeight / 2));
            rightEyePos = new Point((this.Width / 2) + 2, (this.Height / 2) - (eyeHeight / 2));            
            
        }

        //update the whole graphical scene if mouse is being moved
        private void Form1_MouseMove(object sender, MouseEventArgs e)
        {
            mousePoint = ((Control)sender).PointToClient(MousePosition);
            drawPupils();
        }

        //update the whole graphical scene if the window is being adjusted
        private void Form1_Resize(object sender, EventArgs e)
        {
            background = new Rectangle(0, 0, this.Width, this.Height);
            leftEyePos = new Point((this.ClientSize.Width / 2) - (eyeWidth / 2) - 2, (this.ClientSize.Height / 2) - (eyeHeight / 2));
            rightEyePos = new Point((this.ClientSize.Width / 2) + (eyeWidth / 2) + 2, (this.ClientSize.Height / 2) - (eyeHeight / 2));            
            drawPupils();
        }

        private void Form1_Paint(object sender, PaintEventArgs e)
        {
            //calculate rectangle boxes
            leftEye = new Rectangle(leftEyePos.X, leftEyePos.Y, eyeWidth, eyeHeight);
            leftPupil = new Rectangle(leftEyePos.X + eyeWidth / 2, leftEyePos.Y + eyeHeight / 2, pupilSize.Width, pupilSize.Height);

            rightEye = new Rectangle(rightEyePos.X, rightEyePos.Y, eyeWidth, eyeHeight);
            rightPupil = new Rectangle(rightEyePos.X + eyeWidth / 2, rightEyePos.Y + eyeHeight / 2, pupilSize.Width, pupilSize.Height);
                       
            leftEyeCenter = new Point(leftEyePos.X + leftEye.Width / 2, leftEyePos.Y + leftEye.Height / 2);
            rightEyeCenter = new Point(rightEyePos.X + rightEye.Width / 2, rightEyePos.Y + rightEye.Height / 2);

            //create a buffered image
            BufferedGraphicsContext currentContext;
            BufferedGraphics myBuffer;
            currentContext = BufferedGraphicsManager.Current;
            myBuffer = currentContext.Allocate(this.CreateGraphics(),
               this.DisplayRectangle);

            g = this.CreateGraphics();
            myBuffer.Graphics.FillRectangle(RectangleColor, background);
            myBuffer.Graphics.FillEllipse(eyeColor, leftEye);
            myBuffer.Graphics.DrawEllipse(EyePen, leftEye);
            myBuffer.Graphics.FillEllipse(eyeColor, rightEye);
            myBuffer.Graphics.DrawEllipse(EyePen, rightEye);

            myBuffer.Render(g);

            g.Dispose();
        
        }

        private Point getPos(Point eyePos, Point eyeCenter)
        {

            Point pupilPos = new Point();

            //distance between eye and mouse pointer
            delta = new Point(eyeCenter.X - mousePoint.X, eyeCenter.Y - mousePoint.Y);
            deg = Convert.ToInt32((((Math.Atan2(delta.Y, delta.X) + Math.PI) * (180 / Math.PI)) + 180) % 360);
            

            //temp point
            Point tmpLeft = new Point();
            tmpLeft.X = Convert.ToInt32(((Math.Cos((Math.PI / 180) * deg) * leftEye.Width / 2) * (eyeWidth - pupilSize.Width) / eyeWidth) * -1) - pupilSize.Width / 2;
            tmpLeft.Y = Convert.ToInt32(((Math.Sin((Math.PI / 180) * deg) * leftEye.Height / 2) * (eyeHeight - pupilSize.Height) / eyeHeight) * -1) - pupilSize.Height / 2;

            //distances (pythagoras)
            int distPupil = Convert.ToInt32(Math.Sqrt(Math.Pow(tmpLeft.X, 2) + Math.Pow(tmpLeft.Y, 2)));
            int distMouse = Convert.ToInt32(Math.Sqrt(Math.Pow((eyeCenter.X - mousePoint.X), 2) + Math.Pow((eyeCenter.Y - mousePoint.Y), 2)));

            //condition if distance is within
            if (distMouse <= distPupil)
            {
                pupilPos.X = mousePoint.X - ((distMouse / pupilSize.Width));
                pupilPos.Y = mousePoint.Y - ((distMouse  / pupilSize.Height));
            }
            else
            {
                delta = new Point(eyeCenter.X - mousePoint.X, eyeCenter.Y - mousePoint.Y);
                deg = Convert.ToInt32((((Math.Atan2(delta.Y, delta.X) + Math.PI) * (180 / Math.PI)) + 180) % 360);
                pupilPos.X = Convert.ToInt32(((Math.Cos((Math.PI / 180) * deg) * leftEye.Width / 2) * (eyeWidth - pupilSize.Width) / eyeWidth) * -1 + eyePos.X + leftEye.Width / 2) - pupilSize.Width / 2;
                pupilPos.Y = Convert.ToInt32(((Math.Sin((Math.PI / 180) * deg) * leftEye.Height / 2) * (eyeHeight - pupilSize.Height) / eyeHeight) * -1 + eyePos.Y + leftEye.Height / 2) - pupilSize.Height / 2;
            }

            return pupilPos;
        }

        private void drawPupils()
        {
            g = this.CreateGraphics();            
            BufferedGraphicsContext myContext;
            myContext = BufferedGraphicsManager.Current;

            
            leftPupilPos = getPos(leftEyePos, leftEyeCenter);
            rightPupilPos = getPos(rightEyePos,rightEyeCenter);

            
            Rectangle leftPupil = new Rectangle(leftPupilPos, pupilSize);
            Rectangle rightPupil = new Rectangle(rightPupilPos, pupilSize);

            BufferedGraphicsContext currentContext;
            BufferedGraphics myBuffer;
            currentContext = BufferedGraphicsManager.Current;
            myBuffer = currentContext.Allocate(this.CreateGraphics(),
               this.DisplayRectangle);

            //draw the grey background
            myBuffer.Graphics.FillRectangle(RectangleColor, background);
            myBuffer.Graphics.DrawEllipse(EyePen, leftEye);
            myBuffer.Graphics.DrawEllipse(EyePen, rightEye);

            //draw (bright) eye + pupil if left eye is opened, else draw the lid
            if (leftEyeOpened)
            {
                myBuffer.Graphics.FillEllipse(eyeColor, leftEye);
                myBuffer.Graphics.FillEllipse(PupilBrush, leftPupil);
            }
            else
                myBuffer.Graphics.FillEllipse(closedEyeColor, leftEye);

            //draw (bright) eye + pupil if right eye is opened, else draw the lid
            if (rightEyeOpened)
            {
                myBuffer.Graphics.FillEllipse(eyeColor, rightEye);
                myBuffer.Graphics.FillEllipse(PupilBrush, rightPupil);
            }
            else
                myBuffer.Graphics.FillEllipse(closedEyeColor, rightEye);


            myBuffer.Render(g);


            g.Dispose();
        }

         
        private bool pointWithinEye(Point mousePoint, Point eyePos, Point eyeCenter)
        {
            //check if the mouse is within the oval of one eye
            delta = new Point(eyeCenter.X - mousePoint.X, eyeCenter.Y - mousePoint.Y);
            deg = Convert.ToInt32((((Math.Atan2(delta.Y, delta.X) + Math.PI) * (180 / Math.PI)) + 180) % 360);
            Point tmpLeft = new Point();
            tmpLeft.X = Convert.ToInt32(((Math.Cos((Math.PI / 180) * deg) * leftEye.Width / 2) * (eyeWidth - pupilSize.Width) / eyeWidth) * -1) - pupilSize.Width / 2;
            tmpLeft.Y = Convert.ToInt32(((Math.Sin((Math.PI / 180) * deg) * leftEye.Height / 2) * (eyeHeight - pupilSize.Height) / eyeHeight) * -1) - pupilSize.Height / 2;
            int distPupil = Convert.ToInt32(Math.Sqrt(Math.Pow(tmpLeft.X, 2) + Math.Pow(tmpLeft.Y, 2)));
            int distMouse = Convert.ToInt32(Math.Sqrt(Math.Pow((eyeCenter.X - mousePoint.X), 2) + Math.Pow((eyeCenter.Y - mousePoint.Y), 2)));

            if (distMouse <= distPupil)
                return true;
            else
                return false;
        }

        private void Form1_MouseClick(object sender, MouseEventArgs e)
        {
            //Put mouse x + y in a point
            Point mousePoint = new Point(e.X, e.Y);

            //check if the user clicked
            if ((e.Button == MouseButtons.Left) && (pointWithinEye(mousePoint,leftEyePos, leftEyeCenter)))
            {
                if (!leftEyeOpened)
                    leftEyeOpened = true;
                else
                    leftEyeOpened = false;

            } //here it once said MouseButtons.Right (so you had to click the right mouse button in order to close the right eye)
            else if (e.Button == MouseButtons.Left && (pointWithinEye(mousePoint,rightEyePos, rightEyeCenter)))
            {
                if (!rightEyeOpened)
                    rightEyeOpened = true;
                else
                    rightEyeOpened = false;
            }
            


        }
        
    }
}
